package com.norns.torque.view

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.view.View
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.drake.brv.utils.bindingAdapter
import com.drake.brv.utils.divider
import com.drake.brv.utils.linear
import com.drake.brv.utils.models
import com.drake.brv.utils.setup
import com.gyf.immersionbar.ImmersionBar
import com.hi.dhl.binding.viewbind
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.enums.PopupPosition
import com.norns.torque.BluetoothViewModel
import com.norns.torque.ExcelViewModel
import com.norns.torque.R
import com.norns.torque.bluetooth.ChatServer
import com.norns.torque.databinding.ActivityPeakValueBinding
import com.norns.torque.databinding.ItemPeakValueBinding
import com.norns.torque.dialog.AppCommonDialog
import com.norns.torque.dialog.PwdDialog
import com.norns.torque.entrty.DeviceConfig
import com.norns.torque.entrty.ScaleBean
import com.norns.torque.utils.AppConstant
import com.norns.torque.utils.AppContext
import com.norns.torque.utils.DataConversion
import com.permissionx.guolindev.PermissionX
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.lang.Float.intBitsToFloat
import java.time.LocalDateTime


/**
 * 峰值模式
 */
class PeakValueActivity : AppCompatActivity() {
    private val binding: ActivityPeakValueBinding by viewbind()
    private val bluetoothViewModel: BluetoothViewModel by viewModels()
    private val excelViewModel: ExcelViewModel by viewModels()
    private val arrayList:ArrayList<ScaleBean> = ArrayList()
    private var isStartLoopModel:Boolean=false
    companion object {
        const val countdown: Int = 157
    }
    override fun attachBaseContext(newBase: Context?) {
        super.attachBaseContext(newBase)
        overrideFontScale(newBase)
    }

    /**
     * 重置配置 fontScale：保持字体比例不变，始终为 1.
     */
    private fun overrideFontScale(context: Context?) {
        if (context == null) return
        context.resources.configuration.let {
            it.fontScale = 1f // 保持字体比例不变，始终为 1.
            applyOverrideConfiguration(it) // 应用新的配置
        }
    }


    private val handler: Handler = object : Handler(Looper.myLooper()!!) {
        override fun handleMessage(msg: android.os.Message) {
            if (countdown == msg.what) {
                val connectionState = ChatServer.connectedState
                if (connectionState != AppConstant.connectionSuccess) {
                    Toast.makeText(this@PeakValueActivity, "设备连接失败", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initView()
        initData()
        subscribeToModel()
    }

    private fun initView() {
        ImmersionBar.with(this).statusBarColor(R.color.main)
            .navigationBarColor(R.color.main)
            .autoStatusBarDarkModeEnable(true,0.2f)
            .init()
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        val blackColor = getColor(R.color.green_color)
        binding.tvContentState.text = "已连接"
        binding.tvContentState.setTextColor(blackColor)

        binding.btnBack.setOnClickListener {
            bluetoothViewModel.disconnect()
            finish()
        }
        binding.btnMore.setOnClickListener {
            bluetoothViewModel.disconnect()
            if (ChatServer.contentType==ChatServer.NetWork) {
                startActivity(Intent(this@PeakValueActivity, WiFiDeviceActivity::class.java))
            }else{
                startActivity(Intent(this@PeakValueActivity, ScanActivity::class.java))
            }
            finish()
        }
        binding.tvLoop.setOnClickListener {
            if (bluetoothViewModel.isConnected()){
                isStartLoopModel=true
                //关闭追踪模式
                bluetoothViewModel.closeAutoPeak()
            }else{
                Toast.makeText(this@PeakValueActivity, "设备连接已断开", Toast.LENGTH_SHORT).show()
            }
        }
        binding.tvSetting.setOnClickListener {
            bluetoothViewModel.closeAutoPeak()
            bluetoothViewModel.stopGetDeviceRssi()
            startActivity(Intent(this@PeakValueActivity, SettingActivity::class.java))
        }
        binding.tvDownload.setOnClickListener {
            checkWritePermissions()
        }
        binding.valueList.divider {
            setDivider(5, true)
            endVisible = true
        }.linear()
            .setup {
                addType<ScaleBean>(R.layout.item_peak_value)
                onBind {
                    val binding = getBinding<ItemPeakValueBinding>() // ViewBinding/DataBinding都支持
                    val bean = getModel<ScaleBean>()
                    binding.tvTargetValue.text = bean.targetValue.toString()
                    binding.tvUnitValue.text = bean.unit
                    val precisionValue="${bean.precisionDegree}%"
                    binding.tvPrecisionDegree.text = precisionValue
                    binding.tvCount.text = bean.count
                    binding.tvPeakValue.text = bean.value.toString()
                    binding.tvTime.text = bean.getDateStr()
                    val offset=bean.targetValue*(bean.precisionDegree/100f)
                    val upValue=bean.targetValue+offset
                    val dowValue=bean.targetValue-offset
                    if (bean.value<dowValue){
                        val blackColor = getColor(R.color.black)
                        binding.tvPeakValue.setTextColor(blackColor)
                    }else if (bean.value>upValue){
                        val errorColor = getColor(R.color.error_color)
                        binding.tvPeakValue.setTextColor(errorColor)
                    }else{
                        val greenColor = getColor(R.color.green_color)
                        binding.tvPeakValue.setTextColor(greenColor)
                    }
                }
                R.id.itemRoot.onLongClick {
                    val binding = getBinding<ItemPeakValueBinding>()
                    val bean = getModel<ScaleBean>()
                    showPoPu(bean,binding.tvPeakValue)
                }

            }
        binding.valueList.models=arrayList


    }
   private fun showPoPu(bean:ScaleBean,atView: View){
        XPopup.Builder(this@PeakValueActivity)
            .atView(atView) // 依附于所点击的View，内部会自动判断在上方或者下方显示
            .hasShadowBg(false)
            .isDestroyOnDismiss(true)
            .popupPosition(PopupPosition.Right)
            .hasNavigationBar(true)
            //.isCenterHorizontal(true)
            //.offsetX(80)
            //.offsetY(-50)
            .asAttachList(
                arrayOf<String>("删除", "删除全部", "导出全部"),
                null
            ) { position, text ->
                if (position==0){
                    val appCommonDialog= AppCommonDialog.newInstance("确认删除该数据?")
                    appCommonDialog.setClickListener { r->
                        if (r){
                            arrayList.clear()
                            excelViewModel.deleteScale(bean)
                        }
                    }
                    appCommonDialog.show(supportFragmentManager,"appCommonDialog")
                }else if (position==1){
                    val pwdDialog= PwdDialog.newInstance()
                    pwdDialog.setClickListener { r->
                        if (r){
                            arrayList.clear()
                            binding.valueList.adapter?.notifyDataSetChanged()
                            excelViewModel.deleteAllScale()
                        }
                    }
                    pwdDialog.show(supportFragmentManager,"pwdDialog")
                }else if (position==2){
                    checkWritePermissions()
                }
            }
            .show()
    }

    @SuppressLint("MissingPermission")
    private fun initData() {
        excelViewModel.initDataBase()
    }

    override fun onResume() {
        super.onResume()
        bluetoothViewModel.setResultMessageState(false)
        bluetoothViewModel.readDeviceValue()
        bluetoothViewModel.startGetDeviceRssi()
    }


    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }


    private fun checkWritePermissions() {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
//            // 访问外部存储
//            val locationPermission: Boolean = PermissionX.isGranted(
//                applicationContext,
//                Manifest.permission.MANAGE_EXTERNAL_STORAGE
//            )
//        }

        val requestList = ArrayList<String>()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
            requestList.add(Manifest.permission.READ_MEDIA_IMAGES)
            requestList.add(Manifest.permission.READ_MEDIA_AUDIO)
            requestList.add(Manifest.permission.READ_MEDIA_VIDEO)
        }else{
            requestList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
        if (requestList.isNotEmpty()) {
            PermissionX.init(this)
                .permissions(requestList)
                .onExplainRequestReason { scope, deniedList ->
                    val message = "需要您同意以下权限才能正常使用"
                    scope.showRequestReasonDialog(deniedList, message, "同意", "取消")
                }
                .request { allGranted, grantedList, deniedList ->
                    if (allGranted) {
                        excelViewModel.createExcelFile()
                        //Toast.makeText(this, "所有申请的权限都已通过", Toast.LENGTH_SHORT).show()
                    } else {
                        Toast.makeText(this, "您拒绝了如下权限：$deniedList", Toast.LENGTH_SHORT)
                            .show()
                    }
                }
        }

//        // 访问外部存储
//        val readFilePermission: Boolean = PermissionX.isGranted(applicationContext,
//            Manifest.permission.READ_EXTERNAL_STORAGE
//        )
//        val writeFilePermission: Boolean = PermissionX.isGranted(applicationContext,
//            Manifest.permission.WRITE_EXTERNAL_STORAGE
//        )
//        if (!readFilePermission || !writeFilePermission) {
//            // 有一个或多个权限未授予，需要申请权限
//            requestWritePermission()
//        } else {
//            // 权限已授予
//            excelViewModel.createExcelFile()
//        }
    }

    private fun requestWritePermission() {
        PermissionX.init(this)
            .permissions(
                arrayListOf<String>(
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                )
            )
            .onExplainRequestReason { scope, deniedList ->
                val message = "需要您同意以下权限才能正常使用"
                scope.showRequestReasonDialog(deniedList, message, "同意", "取消")
            }
            .request { allGranted, grantedList, deniedList ->
                if (allGranted) {
                    excelViewModel.createExcelFile()
                    Toast.makeText(this, "所有申请的权限都已通过", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "您拒绝了如下权限：$deniedList", Toast.LENGTH_SHORT).show()
                }
            }
    }


    private fun subscribeToModel() {
        excelViewModel.viewState.observe(this) { toast ->
            Toast.makeText(this, toast, Toast.LENGTH_SHORT).show()
        }
        ChatServer.contentDevice.observe(this){value->
            binding.tvDeviceMac.text = value.address
        }
        excelViewModel.listScale.observe(this){values->
            arrayList.addAll(0,values)
            binding.valueList.bindingAdapter.notifyDataSetChanged()
        }


        bluetoothViewModel.connectionState.observe(this) { value ->
            if (value== AppConstant.connectionField) {
                binding.tvContentState.text = "连接已断开"
                val errorColor = getColor(R.color.error_color)
                binding.tvContentState.setTextColor(errorColor)
            } else if (value==AppConstant.connectionSuccess)  {
                val blackColor = getColor(R.color.green_color)
                binding.tvContentState.text = "已连接"
                binding.tvContentState.setTextColor(blackColor)
            }
        }
        bluetoothViewModel.bluetoothRssi.observe(this) { vaule ->
            binding.tvDistance.text = "${vaule}dbm"
        }
        bluetoothViewModel.bluetoothState.observe(this) { value ->
            if (value == BluetoothAdapter.STATE_OFF) {
                binding.tvContentState.text = "蓝牙已关闭"
                val errorColor = getColor(R.color.error_color)
                binding.tvContentState.setTextColor(errorColor)
                ChatServer.disconnect()
            }
            if (value == BluetoothAdapter.STATE_ON) {
                binding.tvContentState.text = "正在连接蓝牙..."
                val errorColor = getColor(R.color.blue_color)
                binding.tvContentState.setTextColor(errorColor)
                ChatServer.autoConnection()
                handler.sendEmptyMessageDelayed(countdown, 6000)
            }
        }

        //获取设备发送的消息
        bluetoothViewModel.messages.observe(this) { messages ->
            if (messages.startsWith("AA44")){
                val cmdCodeLengthStr = messages.substring(6, 8)
                val cmdCodeLength = Integer.parseInt(cmdCodeLengthStr, 16) * 2
                Timber.d("命令长度${cmdCodeLength}")
                if (messages.length <(8 + cmdCodeLength)){
                    lastMessage=messages
                }else{
                    praceMessage(messages)
                }
            }else{
                if (messages.endsWith("0D0A") && !TextUtils.isEmpty(lastMessage)){
                    lastMessage+=messages
                    Timber.d("2222:${lastMessage}")
                    praceMessage(lastMessage)
                }
            }
        }

    }
    private fun createScaleBean(value:Float){
        lifecycleScope.launch {
           val scaleBean = withContext(Dispatchers.IO){
                val scaleBean = ScaleBean()
                scaleBean.date = LocalDateTime.now()
                scaleBean.deviceName =  DeviceConfig.bluetoothName
                scaleBean.targetValue = DeviceConfig.targetValue
                scaleBean.unit=bluetoothViewModel.getUnitString(DeviceConfig.unitValue)
                scaleBean.precisionDegree=DeviceConfig.precisionValue
                val size=binding.valueList.models?.size?:0
                scaleBean.count="${size+1}"
                scaleBean.value=value
                excelViewModel.insertScale(scaleBean)
                scaleBean
            }
            arrayList.add(0,scaleBean)
            binding.valueList.bindingAdapter.notifyDataSetChanged()
        }
    }
    private var lastMessage:String=""
   private fun praceMessage(messageText:String){
       lastMessage=""
        if (messageText.startsWith("AA44")) {
            val cmdCodeStr = messageText.substring(4, 6)
            val cmdCode = cmdCodeStr.toInt(16)
            val cmdCodeLengthStr = messageText.substring(6, 8)
            val cmdCodeLength = Integer.parseInt(cmdCodeLengthStr, 16) * 2
            val cmdDataStr = try{
                 messageText.substring(8, 8 + cmdCodeLength)
            }catch (e:Exception){
                ""
            }
            if (cmdDataStr.isEmpty()){// 获取剪贴板管理器
                val clipboard: ClipboardManager? = AppContext.context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
                if (clipboard != null) {
                    // 创建一个剪贴数据对象并设置要复制的文本
                    val clip = ClipData.newPlainText("label", messageText)
                    // 将剪贴数据对象复制到剪贴板
                    clipboard.setPrimaryClip(clip)
                    // 提示用户复制成功
                    //Toast.makeText(applicationContext, "已复制到剪贴板", Toast.LENGTH_SHORT).show()
                }
                Toast.makeText(this, "设备命令错误", Toast.LENGTH_SHORT).show()
                return
            }
            when (cmdCode) {
                255 ->{
                    bluetoothViewModel.setResultMessageState(true)
                    //打开自动上传
                    bluetoothViewModel.openAutoPeak()
                    praceConfig(cmdDataStr)
                }
                5 -> {//peak值返回
                    val peakValue = intBitsToFloat(Integer.reverseBytes(Integer.parseUnsignedInt(cmdDataStr, 16)))
                    val number=(Math.round(peakValue*1000)/1000f)
                    Timber.i( "设备Peak值:${peakValue} ${number}")
                    createScaleBean(number)
                }
                9 -> {
                    val cmdData = cmdDataStr.toInt(16)
                    if (cmdData == 2) {//关闭追踪模式
                        if (isStartLoopModel){
                            isStartLoopModel=false
                            startActivity(Intent(this@PeakValueActivity, LoopValueActivity::class.java))
                            finish()
                        }
                    } else {
                       val message= if (isStartLoopModel){
                            isStartLoopModel=false
                            "关闭追踪模式失败"
                        }else{
                            "开启追踪模式失败"
                        }
                        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }
    }
   private fun praceConfig(cmdDataStr:String){
       val rangValueStr=cmdDataStr.substring(0,4)
       DeviceConfig.range=rangValueStr.toInt(16)
       Timber.d("设备量程值:${DeviceConfig.range}  length:${cmdDataStr.length}")
       Timber.d("cmdDataStr:${cmdDataStr}")
       binding.tvContent.text="量程:${DeviceConfig.range}"
       //目标值
       val targetValueStr=cmdDataStr.substring(4,8)
       DeviceConfig.targetValue=targetValueStr.toInt(16)
       Timber.d("设备目标值:${DeviceConfig.targetValue}  length:${cmdDataStr.length}")
       //精度
       val precisionValueStr=cmdDataStr.substring(8,10)
       Timber.d("设备精度值:${precisionValueStr}")
       DeviceConfig.precisionValue=precisionValueStr.toInt(16)
       //单位
       val unitStr=cmdDataStr.substring(10,12)
       Timber.d("设备单位值:${unitStr} length:${cmdDataStr.length}")
       DeviceConfig.unitValue=unitStr.toInt(16)

       if (cmdDataStr.length<=24){
           DeviceConfig.bluetoothName=ChatServer.contentDevice.value?.name?:"Unknown"
           binding.tvDeviceName.text = DeviceConfig.bluetoothName
       }else {
           val deviceNameCode = cmdDataStr.substring(24)
           val deviceName=DataConversion.hexStringToOriginalString(deviceNameCode)
           Timber.d("设备名称:${deviceName}:${deviceNameCode}")
           DeviceConfig.bluetoothName=deviceName
           binding.tvDeviceName.text = deviceName
       }
    }
}